Skip navigation
NintendoAge
Welcome, Guest! Please Login or Join
Loading...

## Nerdy Nights Sound: Part 4 sound engine skeleton

- Posts 1 - 18 of 18
- 1

Sep 4, 2009 at 11:27:12 AM
MetalSlime (0)
(Thomas Hjelm) < Crack Trooper >
Posts: 140 - Joined: 08/14/2008
Japan
Profile
Last Week: Periods, Lookup Tables
This Week: Sound Engine Basics. We will setup the framework to get our sound engine running.
Sound Engine
Now that we know how to get notes to play we can start thinking about our sound engine. What do we want it to be able to do? How will the main program interact with it?
It's good practice to separate the different pieces of your program. The sound engine shouldn't be messing with main program code and vice-versa. If you mix them, your code becomes harder to read, the danger of variable conflicts increases and you open yourself up to hard-to-find bugs. If you keep the different pieces of your program separate, you get the opposite: your code reads well, you avoid variable conflicts, and bugs are easier to trace. Separation also improves your ability to reuse code. If your sound engine only accesses its own internal routines and variables, it makes it that much easier to pull it out from one game and plug it into another.
There has to be some communication between the main program and the sound engine of course. The main program needs to be able to tell the sound engine to do things like: "Play song 2" or "shut up". But we don't want the main program sticking its nose in the sound engine's business. We only want it to issue commands. The sound engine will handle the rest on its own.
To set this up, we will create a small set of subroutines that the main program can use to invoke the sound engine and give it commands. I'll call these subroutines "entrances". We want as few entrances into the sound engine as possible. The sound engine itself will have several internal subroutines it can work with, but the main program will only use the entrances.
Entrances
So what will our entrance subroutines be? We need to think about what the main program would need to tell the sound engine to do. Here is a list of entrances we might want for our sound engine:
-Initialize sound engine (sound_init)
-Load new song/sfx (sound_load)
-Play a frame of music/sfx (sound_play_frame)
-Disable sound engine (sound_disable)
The names in paranthesis are what I'm going to call the subroutines in code. I prefixed them with sound_ for readability. You can tell at a glance that they are sound routines. Here is a rundown of what our commands will do:
sound_init will enable channels and silence them. It will also initialize sound engine variables.
sound_load will take a song/sfx number as input. It will use that song number to index into a table of pointers to song headers. It will read the appropriate header and set up sound engine variables. If that didn't make sense, don't worry. We'll be covering this stuff next week.
sound_play_frame will advance the sound engine by one frame. It will run the note timers, read from the data streams (if necessary), update sound variables and make writes to the APU ports. This stuff will also be covered in future weeks.
sound_disable will disable channels via $4015 and set a disable flag variable.
We already know enough to knock out two of those, sound_init and sound_disable. Let's write them now. We'll write skeleton code for the other entrance subroutines as well. A few things to mention before we do that though:
RAM
A sound engine requires a lot of RAM. A large sound engine might even take up a full page of RAM. For this tutorial, we'll stick all our sound engine variables on the $300 page of RAM. There is nothing magic about this number. I chose $300 for convenience. $000 is your zero-page RAM. $100 is your stack. If you completed the original Nerdy Nights series, $200 will be your Sprite OAM. So $300 is next in line.
ROM
The sound engine itself won't require a lot of ROM space for code, but if you have a lot of music your song data might take up a lot of space. For this reason, I'm going to change our header to give us two 16k PRG-ROM banks, like this:
.inesprg 2 ;2x 16kb PRG code
Now we have twice as much ROM space, just in case we need it. BTW, this is the maximum amount of ROM we can have without using a mapper.
Noise Channel
I purposely haven't covered the Noise channel yet. We will want to silence it in our init code though, so I will go ahead and teach that much. Noise channel volume is controlled via port $400C. It works the same as $4000/$4004 does for the Square channels, except there is no Duty Cycle control:
NOISE_ENV ($400C)
76543210
||||||
||++++- Volume
|+----- Saw Envelope Disable (0: use internal counter for volume; 1: use Volume for volume)
+------ Length Counter Disable (0: use Length Counter; 1: disable Length Counter)
Like the Squares, we will silence the Noise channel by setting both disable flags, and setting the Volume to 0.
Skeleton Sound Engine
Let's write the entrance subroutines to our sound engine. Most of this code should be very familiar to you if you completed the first three tutorials in this series.
.rsset $0300 ;sound engine variables will be on the $0300 page of RAM
sound_disable_flag .rs 1 ;a flag variable that keeps track of whether the sound engine is disabled or not.
;if set, sound_play_frame will return without doing anything.
.bank 0
.org $8000 ;we have two 16k PRG banks now. We will stick our sound engine in the first one, which starts at $8000.
sound_init:
lda #$0F
sta $4015 ;enable Square 1, Square 2, Triangle and Noise channels
lda #$30
sta $4000 ;set Square 1 volume to 0
sta $4004 ;set Square 2 volume to 0
sta $400C ;set Noise volume to 0
lda #$80
sta $4008 ;silence Triangle
lda #$00
sta sound_disable_flag ;clear disable flag
;later, if we have other variables we want to initialize, we will do that here.
rts
sound_disable:
lda #$00
sta $4015 ;disable all channels
lda #$01
sta sound_disable_flag ;set disable flag
rts
sound_load:
;nothing here yet
rts
sound_play_frame:
lda sound_disable_flag
bne .done ;if disable flag is set, don't advance a frame
;nothing here yet
.done:
rts
Driving the Sound Engine
We have the framework setup for our sound engine to run. The main program now has subroutines it can call to issue commands to the sound engine. Most of them don't do anything yet, but we can still integrate them into the main program. First we will want to make a call to sound_init somewhere in our reset code:
RESET:
sei
cld
ldx #$FF
txs
inx
;... clear memory, etc
jsr sound_init
;... more reset stuff
Next we need something to drive our sound engine. Music is time-based. In any piece of music, assuming a constant tempo, each quarter note needs to last exactly as long as every other quarter note. A whole note has to be exactly as long as four quarter notes. If our sound engine is going to play music, it needs to be time-based as well. We have a subroutine, sound_play_frame, that will advance our sound engine a frame at a time. Now we need to ensure it gets called repeatedly at a regular time interval.
One way to do this is to stick it in the NMI. Recall that when enabled, the NMI will trigger at the start of every vblank. Vblank is the only safe time to write to the PPU, so the NMI is typically full of drawing code. We don't want to waste our precious vblank time running sound code, but what about after we are finished drawing? If we stick our call to sound_play_frame at the end of NMI, after the drawing code, we are set. sound_play_frame gets called once per frame, and we avoid stepping on the PPU's toes. And since sound_play_frame doesn't write to the PPU registers, it doesn't matter if our sound code spills out of vblank.
Let's setup the NMI to drive our sound engine:
NMI:
pha ;save registers
txa
pha
tya
pha
;do sprite DMA
;update palettes if needed
;draw stuff on the screen
;set scroll
jsr sound_play_frame ;run our sound engine after all drawing code is done.
;this ensures our sound engine gets run once per frame.
lda #$00
sta sleeping ;did you do your homework and read Disch's document last week?
;http://nesdevhandbook.googlepages...
pla ;restore registers
tay
pla
tax
pla
rti
.include
To further separate our sound engine from the main program, we can keep all our sound engine code in a separate file. NESASM3 gives us a directive .include that we can use to copy a source file into our main program. We actually used this directive last week to include the note_table.i file, which contained our period lookup table.
Using .include to copy a source file into our code is very similar to how we use .incbin to import a .chr file. Assuming our sound engine code is saved in a file called sound_engine.asm, we will add the following code to our main program:
.include "sound_engine.asm"
We will continue to include note_table.i, but since it is part of our sound engine we will stick the .include directive in the sound_engine.asm file.
It's not bad practice to use includes a lot. You can pull your joypad routines out and stick them in their own file. You can have separate files for your gamestate code, for your PPU routines and for just about anything else you can think of. Breaking up your code like this will make it easier to find things as your program gets larger and more complicated. It also makes it easier to plug your old routines into new programs.
Putting It All Together
Download and unzip the skeleton.zip sample files. Make sure skeleton.asm, sound_engine.asm, skeleton.chr, note_table.i, sound_data.i and skeleton.bat are all in the same folder as NESASM3, then double click skeleton.bat. That will run NESASM3 and should produce the skeleton.nes file. Run that NES file in FCEUXD SP.
I've hardcoded sound_load and sound_play_frame to play a little melody on the Square 1 channel. It uses a simple frame counter to control note speed. The data for the music is found in the sound_data.i file. Use the controller to interact with the sound engine. Controls are as follows:
A: Play sound from the beginning (sound_load)
B: Initialize the sound engine (sound_init)
Start: Disable sound engine (sound_disable)
Try editing sound_engine.asm to change the data stream that sound_play_frame reads from. The different data streams available are located in sound_data.i. Try adding your own data stream to sound_data.i too. Use the note symbols we made last week and terminate your data stream with $FF.
Homework: Write two new sound engine entrance subroutines for the main program to use:
1. sound_pause: pauses playback of the sound, but retains the current position in the data stream.
2. sound_unpause: if the sound is currently paused, resumes play from the saved position.
Then modify handle_joypad to allow the user to pause/unpause the music.
Homework #2: If the ideas presented in Disch's The Frames and NMIs document are still fuzzy in your head, read it again.
Extra Credit: See if you can understand how my drawing buffer works. Use Disch's document to help you. I won't cover drawing buffers in these sound tutorials, for obvious reasons, but it is definitely worth your time to learn how to use them.
Next week: Sound Data, Pointer Tables, Headers
-------------------------
MetalSlime runs away
My nesdev blog: http://tummaigames.com/blog...
Edited: 10/23/2009 at 04:42 AM by MetalSlime
Sep 4, 2009 at 3:53:13 PM
udisi (88)
< King Solomon >
Posts: 3261 - Joined: 11/15/2006
United States
Profile
This is pretty neat. I may neat to rewrite my NMI: I've read Disch's document, but don't quite understand everything he does in it. I'm hesitant to change my NMI right now, just cause it'll probably break my game since I don't understand what's all happening there yet.
should a sound engine always go in the first bank? I'm pretty sure the code runs banks in order, and since music can take a long time, you may always want the sound to run first.
the .i files gave me some trouble at first, cause I couldn't open them with windows, so I made copies of them and converted them to .txt files so I could look at them in notepad. I can see what they're doing now, so I'm pretty sure I can write a different tune to play. According to the sound_data.1, it's playing 17 ascending notes on the 3 channels then writing $FF which I assume is a flag to stop.
Sep 4, 2009 at 5:56:51 PM
MetalSlime (0)
(Thomas Hjelm) < Crack Trooper >
Posts: 140 - Joined: 08/14/2008
Japan
Profile
Originally posted by: udisi
This is pretty neat. I may neat to rewrite my NMI: I've read Disch's document, but don't quite understand everything he does in it. I'm hesitant to change my NMI right now, just cause it'll probably break my game since I don't understand what's all happening there yet.
Keep rereading it and it will eventually click. That's been my experience with NES documents . You can probably get away with not rewriting your NMI as long as you are able to stick the call to the sound engine in there somewhere to ensure the sound engine is run once per frame.
Originally posted by: udisi
should a sound engine always go in the first bank? I'm pretty sure the code runs banks in order, and since music can take a long time, you may always want the sound to run first.
It doesn't matter. You can stick the sound engine anywhere. The order the code is run doesn't have to anything to do with bank order. On startup, code execution starts at the address you state in the RESET vector. Then it executes one instruction at a time, only jumping/branching where you explicitly tell it to jump.
If you were using a mapper, you'd probably want your sound engine in a swappable bank rather than the fixed bank, but other than that it doesn't matter where you stick it.
the .i files gave me some trouble at first, cause I couldn't open them with windows, so I made copies of them and converted them to .txt files so I could look at them in notepad. I can see what they're doing now, so I'm pretty sure I can write a different tune to play.
Sorry about that. I've seen other people put a .i extension on their includes so I was just copying the convention. They're just text files. You should be able to open them from Notepad's File->Open without changing their extension.
According to the sound_data.1, it's playing 17 ascending notes on the 3 channels then writing $FF which I assume is a flag to stop.
Almost. If you look at sound_play_frame in sound_engine.asm, you'll see that I only write to the Square 1 channel. The different data streams just play a different variety of ascending notes. You're right about $FF. It terminates the data streams.
Try tracing through sound_play_frame and see if you can follow what it's doing. Feel free to ask more questions if there's something that's still unclear.
-------------------------
MetalSlime runs away
My nesdev blog: http://tummaigames.com/blog...
Sep 14, 2009 at 1:08:59 AM
udisi (88)
< King Solomon >
Posts: 3261 - Joined: 11/15/2006
United States
Profile
well, I have the skeleton sound engine in my game now. The sound_play_frame works fine in my NMI. It doesn't interfere with anything that I can see. I have it play the scale when the game comes on and I can still use the controller buttons, so this works better than what I had tried before.
I set the sound engine to disable when I select something. My plan being I can re-enable and load a different scale when the next screen comes up. we'll see.
I was looking at the sound engine code itself, and thinking of making a variable to control looping. Like if gamestate is still the same, then loop. kinda treating the scale as a song.
Probably thinking ahead a bit here, but I was trying to see how to have a song play and still have soundfx. since sound fx will use the same channel as a song, I need to come up with a way to still progress the song data, but mute it and load the sound fx, and then return to the song when the soundfx is done.
Still playing with this a bit, looking at what of things may be useful as a variable. maybe a tempo variable, to handle the CMP frame.
I assume that future tutorial will add the other channels in. I have someone who did music for me. The songs are done with a tracker program though and in NSF, so I'm thinking they may need to be re-written to work in this engine. I'd use the NSF player route, but I don't know how I'd do that and still be able to use soundfx.
Sep 14, 2009 at 9:25:23 AM
MetalSlime (0)
(Thomas Hjelm) < Crack Trooper >
Posts: 140 - Joined: 08/14/2008
Japan
Profile
Originally posted by: udisi
well, I have the skeleton sound engine in my game now. The sound_play_frame works fine in my NMI. It doesn't interfere with anything that I can see. I have it play the scale when the game comes on and I can still use the controller buttons, so this works better than what I had tried before.
I set the sound engine to disable when I select something. My plan being I can re-enable and load a different scale when the next screen comes up. we'll see.
I was looking at the sound engine code itself, and thinking of making a variable to control looping. Like if gamestate is still the same, then loop. kinda treating the scale as a song.
Probably thinking ahead a bit here, but I was trying to see how to have a song play and still have soundfx. since sound fx will use the same channel as a song, I need to come up with a way to still progress the song data, but mute it and load the sound fx, and then return to the song when the soundfx is done.
Still playing with this a bit, looking at what of things may be useful as a variable. maybe a tempo variable, to handle the CMP frame.
I assume that future tutorial will add the other channels in. I have someone who did music for me. The songs are done with a tracker program though and in NSF, so I'm thinking they may need to be re-written to work in this engine. I'd use the NSF player route, but I don't know how I'd do that and still be able to use soundfx.
Glad the the engine is working with your game. Good comments too. You already forsee some of the complications we'll run into. Some responses to your comments:
1) You likely won't ever need to disable the sound engine. Sound effects will terminate on their own when they finish playing. For forever-looping songs you'll be able to switch to a new song whenever you want. If for some reason you'd want no song to play, you could have a "silence song" that will hush up the music channels.
2) We'll get to looping in a future lesson, but the way we'll do it is by having an opcode in the music data that will tell the sound engine to jump back to an earlier part in the data stream.
3) Dealing with channel conflicts between music and sfx is very important. I'm going to talk about it a bit in the next lesson (which is almost finished). The way we'll handle it is to have the music and sfx both running their streams in RAM, but when it comes time to write to the APU regs we'll make sure the sfx data gets written instead of the music.
4) The simple frame counter that we have in the skeleton sound engine isn't what we will use in the end. It has a lot of problems, the biggest one being that it doesn' let us have variable note lengths (8th note vs. quarter note). Timing, note lengths and tempo will be the topics covered in the the lesson after the next one.
5) Yes, future tutorials will add the other channels in. The next lesson will let us make basic little songs that play on all three tonal channels (Sq1, Sq2, Tri). The next 3 lessons are the really big ones. This is the tentative syllabus:
Part 5 - Pointer tables, playing on multiple channels at once, music/sfx channel conflicts
Part 6 - Timing, note length and tempo, buffering APU writes (maybe?), rests?
Part 7 - Opcodes, RTS Trick, Looping
Part 8 - Volume Envelopes, Transposing
Part 9 - Noise channel?
Part 10+ - other bells and whistles
6) You will have to convert the songs in your NSF to fit the music format of our sound engine. It's unavoidable. On the NES, every game has a different sound engine with a different format for its sound data. NSF files for game music actually include the game's sound engine in the file. But as long as you know the notes, note lengths and effects, it should be pretty easy to convert.
-------------------------
MetalSlime runs away
My nesdev blog: http://tummaigames.com/blog...
Sep 14, 2009 at 3:22:10 PM
udisi (88)
< King Solomon >
Posts: 3261 - Joined: 11/15/2006
United States
Profile
I swear the sound engine is as big and complicated at the game itself
some many things to handle. I'm just trying to stick with the sound engine to learn how the sound truly works and to be able to have sfx and music at the same time.
I can see why a lot of homebrew go the NSF player route. basically just have to tell a song to play. The bad thing with the nsf way is that the music engine is hidden. You have no idea what's going on to make the sound actually happen, and I don't think you have the versatility to play songs, and sfx at the same time.
Anyway, I went in and added my variable to handle which sfx to play, and added my sfx to the sound data file. so now the nerdy nights engine is running my sounds. Good thing I only had 2 different beeps at
basically handle it like this. I initiate sound when the screen is loaded, then in my program when I wanted to call the sfx I wrote this
LDA #$01
STA sfx
jsr sound_load
or
LDA #$02
STA sfx
jsr sound_load
I added a series of branches in the sound engine to check the sfx variable then load the corresponding data stream.
I had to adjust the frame counter as checking every 8 frames was too slow. ended up making it 4. Now you said you are going to implement a new timing thing later, but for now, I was thinking another variable would work here. nae it something like "time" and add it to my call routine. something like this.
LDA #$04
STA time
LDA #$01
STA sfx
jsr sound_load
it should work well for sfx, but songs will probably change timings mid load and such, so I'm looking forward to seeing how this will be handled.
Sep 15, 2009 at 9:40:49 PM
MetalSlime (0)
(Thomas Hjelm) < Crack Trooper >
Posts: 140 - Joined: 08/14/2008
Japan
Profile
Yes a sound engine is pretty complicated, which I guess is the reason there aren't any tutorials for making one yet.
I've never actually used the FamiTracker engine in a game, but I've heard that it doesn't have sfx support. Writing my own sound engine has been more fun anyway
Glad to see you are playing around with the engine and coming up with solutions to select a sound and a speed. One thing you can do to save some bytes is to put the stores inside the sound_load routine:
ldy #$04 ;time
lda #$01 ;sfx number
jsr sound_load
;...
sound_load:
sty time
sta sfx
; do other load stuff
Having the subroutine take parameters in A and Y and do the stores itself will save you the trouble of having to manually store them everytime.
I finished up Part 5 today. Will post it tonight (Japan time). It's the toughest one so far, but it teaches some really important techniques.
-------------------------
MetalSlime runs away
My nesdev blog: http://tummaigames.com/blog...
Sep 20, 2009 at 5:46:33 PM
Rachel (10)
(Player of Games, Killer of Threads) < Eggplant Wizard >
Posts: 334 - Joined: 05/24/2008
Texas
Profile
Thanks for posting this; great stuff. I wish I'd had Disch's NMI doc when I was first getting started . I have been totally slacking off with programming and everything else NES-related, but now I see that I must get back to it!
-------------------------
Resident collector of and expert on vintage girly games and consoles--especially rare stuff!
Currently playing: Miitomo (iOS), Yoshi's Woolly World (WiiU)
Sep 21, 2009 at 3:16:59 PM
MODERATOR
KHAN Games (87)
(Kevin Hanley) < Bowser >
Posts: 7423 - Joined: 06/21/2007
Florida
Profile
Originally posted by: Rachel
Thanks for posting this; great stuff. I wish I'd had Disch's NMI doc when I was first getting started . I have been totally slacking off with programming and everything else NES-related, but now I see that I must get back to it!
Rachel lives!!!
-------------------------

Website | Facebook | Instagram | Twitter | Youtube
--- | --- | --- | --- | ---
Games I've made: Ultimate Frogger Champion, Sneak n Peek, 8-BIT XMAS 2012, Study Hall, Larry, E.T. - The Extra Terrestrial, The Incident, 4-in-1 Retro Gamepak

Feb 28, 2012 at 10:57:06 AM
muffins (0)
(I am Error.) < Tourian Tourist >
Posts: 44 - Joined: 01/31/2012
Maine
Profile
Question: In the description of the add_to_dbuffer subroutine, you say the following:
; Note: dbuffer starts at $0100. This is the stack page. The
; stack counts backwards from $1FF, and this program is small enough that there
; will never be a conflcit. But for larger programs, watch out.
What does this mean? In the add_to_dbuffer and draw_dbuffer subroutines you appear to be reading everything from $0100 until you hit the termination control (#$00) for a string length. I understand that in this situation we can only have from $0100 to $01FF in RAM for the stack (and therefore that is the maximum length of a buffer) because the sprite shadow OAM is in $0200 - $02FF, but I don't see anything in here that indicates there is a "counting backwards" sequence and I don't know what sort of trouble we could run into here.
-------------------------
Mar 1, 2012 at 12:30:23 AM
MetalSlime (0)
(Thomas Hjelm) < Crack Trooper >
Posts: 140 - Joined: 08/14/2008
Japan
Profile
The trouble comes from the fact that we have two different arbitrarily-sized things (the drawing buffer and the stack) using the same page of RAM. There is a potential for conflict if they cross.
The 6502 uses the $0100-$01FF range of RAM for the stack. The bottom of the stack is $01FF and when values are "pushed" onto the stack, they are placed in memory in descending memory addresses. So for example, say we have an empty stack and we push some values to it like this:
lda #$01
pha
lda #$02
pha
lda #$03
pha
After this code is executed the stack in memory would look like this:
$01FD: #03
$01FE: #02
$01FF: #01
The first value is pushed into $01FF, then the next value into $01FE, and so on in reverse order. That's what I meant by "counting backwards".
You can push values onto the stack manually with PHA, but the 6502 also pushes things onto the stack automatically behind the scenes. For example, every time you call a subroutine with JSR, the 6502 will push a 2-byte return address onto the stack. This allows the program to know where to return to when it encounters an RTS command.
So there is a danger anytime you choose to use the $0100 page of RAM to store game-related variables. If you accidentally overwrite a memory location that is currently in use by the stack, things can go terribly wrong. Look at the following code, assuming an empty stack:
jsr my_subroutine
; blah blah blah
my_subroutine:
lda #$00
sta $01FF
rts
Here we call a subroutine with JSR, which pushes a 2-byte address onto the stack at $01FF and $01FE. Then in the subroutine we change the value of $01FF. When the program hits the RTS, it will pop the 2-byte return address off of the stack, but that address will be the wrong address (because we foolishly changed it!).
In practice, the stack usually doesn't grow very deep. Anything pushed onto the stack is usually popped off soon after. I've never seen the stack come even close to using all 256 bytes of the $0100 page. Since memory is tight on the NES, it's quite common for programmers to use the "front" half of the $0100 page for game variables (like a drawing buffer) rather than seeing that RAM go to waste.
Hope that clears it up. Let me know if you have any questions or need more clarification.s
-------------------------
MetalSlime runs away
My nesdev blog: http://tummaigames.com/blog...
Mar 1, 2012 at 12:59:21 AM
muffins (0)
(I am Error.) < Tourian Tourist >
Posts: 44 - Joined: 01/31/2012
Maine
Profile
That totally makes sense I guess I had assumed that the stack usage in programs was negligible as you mentioned so I didn't know when they would cross but I suppose some data streams could come close if we're not careful. Thanks for the follow up, and for the audio tutorials! There's a lot of good information here and I really feel like I'll be well equipped to get some homebrews brewin in no time
-------------------------
Oct 31, 2014 at 1:20:14 PM
tadashibashi (0)
< Cherub >
Posts: 4 - Joined: 10/31/2014
Profile
I am really interested in seeing the source file for the sound driver. The download link/website seems to be down, does anyone happen to have the file?
Nov 4, 2014 at 10:21:32 PM
MetalSlime (0)
(Thomas Hjelm) < Crack Trooper >
Posts: 140 - Joined: 08/14/2008
Japan
Profile
Oops! I forgot that I was hosting something important on that domain and let it expire. I just re-purchased the domain, so it should be back up. Really sorry about that!
-------------------------
MetalSlime runs away
My nesdev blog: http://tummaigames.com/blog...
Nov 6, 2014 at 4:29:04 AM
user (5)
< El Ripper >
Posts: 1202 - Joined: 05/30/2014
Profile
Originally posted by: MetalSlime
Oops! I forgot that I was hosting something important on that domain and let it expire. I just re-purchased the domain, so it should be back up. Really sorry about that!
Hi MetalSlime!
It is very welcome if you publish these files again. I find your tutorials really interesting!
Cheers!
- user
Nov 22, 2014 at 9:05:15 PM
NESMASTER14 (26)
(color dreams) < King Solomon >
Posts: 4617 - Joined: 04/19/2008
Virginia
Profile
Wow, just saw that the files have been re-hosted again. Thank you! Now I can go through the tutorials again with the proper files. These are great!
-------------------------
Check out my latest NES tune called "Intense" (real hardware)
Dec 1, 2014 at 11:08:45 AM
Baka94 (0)
< Little Mac >
Posts: 73 - Joined: 02/27/2014
Finland
Profile
Originally posted by: MetalSlime
sta sleeping ;did you do your homework and read Disch's document last week?
;http://nesdevhandbook.googlepages.com/theframe.html
The document doesn't exist anymore. Any else place where I can read the same stuff? What is it about? Just general NMI stuff? I'd like to know so I know if I have learned this stuff (maybe just in different way?).
EDIT: Wait, is this just the thing that is used to prevent main loop from running more than once per frame?
Edited: 12/01/2014 at 11:15 AM by Baka94
Dec 1, 2014 at 2:18:22 PM
Roth (66)
(Rob Bryant) < Lolo Lord >
Posts: 1718 - Joined: 09/14/2006
Illinois
Profile
Originally posted by: Baka94
Originally posted by: MetalSlime
sta sleeping ;did you do your homework and read Disch's document last week?
;http://nesdevhandbook.googlepages.com/theframe.html
The document doesn't exist anymore. Any else place where I can read the same stuff? What is it about? Just general NMI stuff? I'd like to know so I know if I have learned this stuff (maybe just in different way?).
EDIT: Wait, is this just the thing that is used to prevent main loop from running more than once per frame?
http://wiki.nesdev.com/w/index.ph... <--- Thar ye's be's!
-------------------------
http://slydogstudios.org...

Login
User Name:
Password
Stay logged in
Forget your login? Join NintendoAge!